package com.xnyzc.lhy.mis.service.impl.cms.role;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.xnyzc.lhy.common.component.config.GlobalConfig;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.datascope.ESysDataScope;
import com.xnyzc.lhy.common.util.CheckUtil;
import com.xnyzc.lhy.common.util.IDUtil;
import com.xnyzc.lhy.common.util.ListToTreeUtil;
import com.xnyzc.lhy.common.util.TokenUtil;
import com.xnyzc.lhy.mis.entity.cms.OaSysMenu;
import com.xnyzc.lhy.mis.entity.cms.OaSysRole;
import com.xnyzc.lhy.mis.entity.cms.OaSysRoleMenu;
import com.xnyzc.lhy.mis.entity.cms.OaSysRoleOffice;
import com.xnyzc.lhy.mis.entity.dictionaries.OaSysDict;
import com.xnyzc.lhy.mis.entity.param.cms.OfficeParam;
import com.xnyzc.lhy.mis.entity.param.cms.RoleReceive;
import com.xnyzc.lhy.mis.entity.result.cms.SysRoleResults;
import com.xnyzc.lhy.mis.entity.result.cms.SysUserResults;
import com.xnyzc.lhy.mis.entity.sidebar.OaSysOffice;
import com.xnyzc.lhy.mis.entity.system.OaSysUser;
import com.xnyzc.lhy.mis.entity.system.OaSysUserRole;
import com.xnyzc.lhy.mis.mapper.cms.OaSysRoleMapper;
import com.xnyzc.lhy.mis.mapper.cms.OaSysRoleMenuMapper;
import com.xnyzc.lhy.mis.mapper.cms.OaSysRoleOfficeMapper;
import com.xnyzc.lhy.mis.mapper.dictionaries.OaSysDictMapper;
import com.xnyzc.lhy.mis.mapper.sidebar.OaSysOfficeMapper;
import com.xnyzc.lhy.mis.mapper.system.OaSysUserMapper;
import com.xnyzc.lhy.mis.mapper.system.OaSysUserRoleMapper;
import com.xnyzc.lhy.mis.service.cms.role.RoleService;
import com.xnyzc.lhy.mis.service.impl.cms.login.LoginServiceImpl;
import com.xnyzc.lhy.mis.service.impl.cms.office.OfficeServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 *  角色相关
 * </p>
 *
 * @author wangshuo
 * @since 2019-08-08
 */
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private OaSysUserMapper oaSysUserMapper;

    @Autowired
    private OaSysRoleMapper oaSysRoleMapper;

    @Autowired
    private OaSysOfficeMapper oaSysOfficeMapper;

    @Autowired
    private LoginServiceImpl loginServiceImpl;

    @Autowired
    private OfficeServiceImpl officeServiceImpl;

    @Autowired
    private OaSysRoleMenuMapper oaSysRoleMenuMapper;

    @Autowired
    private OaSysRoleOfficeMapper oaSysRoleOfficeMapper;

    @Autowired
    private OaSysUserRoleMapper oaSysUserRoleMapper;

    @Autowired
    private OaSysDictMapper oaSysDictMapper;

    /**
     * 获取角色列表
     *
     * @return
     */
    @Override
    public Rv getRoleList() {
        Long userId=TokenUtil.getTokenUserId();
        //查询当前登录
        OaSysUser sysUser=oaSysUserMapper.selectById(userId);
        if(CheckUtil.objIsEmpty(sysUser)){
            throw PangException.create(EErrorCode.noData);
        }
        //查询全部的目录
        List<SysRoleResults> resultslist = oaSysRoleMapper.roleAllList();
        if(!resultslist.isEmpty()){
            for(SysRoleResults source:resultslist){
                source.setDataScopeStr(ESysDataScope.findById(Integer.valueOf(source.getDataScope())).getDesc());
            }
        }
        return Rv.wrap(EErrorCode.success,resultslist);
    }

    /**
     * 获取角色详情
     *
     * @return
     */
    @Override
    public Rv getRoleDetail(Long roleId,String useable) {
        String tag=TokenUtil.getTag();
        Map<String, Object> map = new HashMap<>(16);
        Long userId=TokenUtil.getTokenUserId();
        OaSysOffice office=new OaSysOffice();
        OaSysRole role=new OaSysRole();
        List<OaSysRoleOffice> roleOfficeList=new ArrayList<>();
        List<OaSysRoleMenu> roleMenuList=new ArrayList<>();
        if(CheckUtil.objIsNotEmpty(roleId)){
            role = oaSysRoleMapper.selectById(roleId);
            if(CheckUtil.objIsEmpty(role)){
                throw PangException.create(EErrorCode.noData);
            }
            office = oaSysOfficeMapper.selectById(role.getOfficeId());
            // 查询机构角色关联
            QueryWrapper<OaSysRoleOffice> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(OaSysRoleOffice.ROLE_ID,roleId).eq(OaSysRoleOffice.TAG,tag);
            roleOfficeList=oaSysRoleOfficeMapper.selectList(queryWrapper);
            List<Long> roleOfficeIdList=new ArrayList<>();
            if(!roleOfficeList.isEmpty()){
                for(OaSysRoleOffice roleOffice:roleOfficeList){
                    roleOfficeIdList.add(roleOffice.getOfficeId());
                }
            }
            map.put("roleOfficeIdList", roleOfficeIdList);
            // 查询机构角色关联
            QueryWrapper<OaSysRoleMenu> menuQueryWrapper = new QueryWrapper<>();
            menuQueryWrapper.eq(OaSysRoleMenu.ROLE_ID,roleId).eq(OaSysRoleMenu.TAG,tag);
            roleMenuList=oaSysRoleMenuMapper.selectList(menuQueryWrapper);
            List<Long> roleMenuIdList=new ArrayList<>();
            if(!roleMenuList.isEmpty()){
                for(OaSysRoleMenu roleMenue:roleMenuList){
                    roleMenuIdList.add(Long.valueOf(roleMenue.getMenuId()));
                }
            }
            map.put("roleMenuIdList", roleMenuIdList);
        }
        map.put("role", role);
        map.put("office", office);
        // 返回机构
        List<OaSysOffice> officeList=officeServiceImpl.getOfficeList(userId);
        List<Map<String, Object>> officeMapList = ListToTreeUtil.getOfficeList(officeList,new ArrayList<>(),"");
        JSONArray officeResultList = ListToTreeUtil.listToTree(JSONArray.parseArray(JSON.toJSONString(officeMapList)),"id","pId","children");
        map.put("officeList", officeResultList);
        // 数据范围
        QueryWrapper<OaSysDict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysDict.TYPE,"data_scope").eq(OaSysDict.TAG,tag);
        List<OaSysDict> dataScopeList = oaSysDictMapper.selectList(queryWrapper);
        map.put("dataScopeList", dataScopeList);
        // 角色类型
        QueryWrapper<OaSysDict> roleTypeQueryWrapper = new QueryWrapper<>();
        roleTypeQueryWrapper.eq(OaSysDict.TYPE,"role_type").eq(OaSysDict.TAG,tag);
        List<OaSysDict> roleTypeList = oaSysDictMapper.selectList(roleTypeQueryWrapper);
        map.put("roleTypeList", roleTypeList);
        // 返回目录
        List<OaSysMenu> menuList=loginServiceImpl.getMenuList(userId);
        List<Map<String, Object>> menuMapList = ListToTreeUtil.getMenuList(menuList);
        JSONArray menuResultList = ListToTreeUtil.listToTree(JSONArray.parseArray(JSON.toJSONString(menuMapList)),"id","pId","children");
        map.put("menuList", menuResultList);
        return Rv.wrap(EErrorCode.success,map);
    }

    /**
     * 新增、修改角色
     *
     * @return
     */
    @Override
    public Rv getUpdateRole(Long roleId,String dataScope,String enname,String isSys,String name,Long officeId,String roleType,String useable,List<Long> menuList
    ) {
        Long userId=TokenUtil.getTokenUserId();
        List<String> roleList=TokenUtil.getRoleDataScope();
        if(!roleList.contains(GlobalConfig.DATA_SCOPE_ALL)){
            throw PangException.create(EErrorCode.authErr);
        }
        Date date=new Date();
        // 新增
        if (CheckUtil.objIsEmpty(roleId)){
            OaSysRole role=new OaSysRole();
            roleId=IDUtil.nextId();
            role.setRoleId(roleId);
            role.setDataScope(dataScope);
            role.setEnname(enname);
            role.setIsSys(isSys);
            role.setName(name);
            role.setOfficeId(officeId);
            role.setRoleType(roleType);
            role.setUseable(useable);
            role.setCreateTime(date);
            role.setCreateUser(userId);
            role.setUpdateTime(date);
            role.setUpdateUser(userId);
            oaSysRoleMapper.insert(role);
        }
        // 修改
        else{
            // 需修改的实体
            OaSysRole updateRole=oaSysRoleMapper.selectById(roleId);
            updateRole.setDataScope(dataScope);
            updateRole.setEnname(enname);
            updateRole.setIsSys(isSys);
            updateRole.setName(name);
            updateRole.setOfficeId(officeId);
            updateRole.setRoleType(roleType);
            updateRole.setUseable(useable);
            updateRole.setUpdateTime(date);
            updateRole.setUpdateUser(userId);
            oaSysRoleMapper.updateById(updateRole);
        }
        // 更新角色与菜单关联
        getRoleMenu(roleId,menuList,userId,date);
        // 更新角色与部门关联
        //getRoleOffice(roleReceive,userId,date);
        return Rv.wrap(EErrorCode.updateSuccess);
    }

    /**
     * 更新角色与菜单关联
     * @param userId
     * @param date
     */
    public void getRoleMenu (Long roleId,List<Long> selectMenuList,Long userId,Date date){
        String tag=TokenUtil.getTag();
        List<Long> resList=new ArrayList<>();
        List<OaSysRoleMenu> roleMenuList=getRoleMenuByRole(String.valueOf(roleId));
        if(selectMenuList==null||selectMenuList.isEmpty()){
            QueryWrapper<OaSysRoleMenu> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(OaSysRoleMenu.ROLE_ID,roleId);
            oaSysRoleMenuMapper.delete(queryWrapper);
        }else{
            List<Long> delteMenuList=new ArrayList<>();
            for(OaSysRoleMenu role:roleMenuList){
                if(!selectMenuList.contains(role.getMenuId())){
                    delteMenuList.add(role.getMenuId());
                }
                resList.add(role.getMenuId());
            }
            if(!delteMenuList.isEmpty()){
                QueryWrapper<OaSysRoleMenu> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq(OaSysRoleMenu.ROLE_ID,roleId);
                queryWrapper.in(OaSysRoleMenu.MENU_ID,delteMenuList);
                oaSysRoleMenuMapper.delete(queryWrapper);
            }
        }
        if(selectMenuList!=null&&!selectMenuList.isEmpty()){
            selectMenuList.removeAll(resList);
            if (!selectMenuList.isEmpty()) {
                OaSysRoleMenu roleMenu = null;
                for (int i = 0; i < selectMenuList.size(); i++) {
                    roleMenu = new OaSysRoleMenu();
                    roleMenu.setLinkedId(IDUtil.nextId());
                    roleMenu.setMenuId(selectMenuList.get(i));
                    roleMenu.setRoleId(roleId);
                    roleMenu.setTag(tag);
                    roleMenu.setCreateTime(date);
                    roleMenu.setCreateUser(userId);
                    roleMenu.setUpdateTime(date);
                    roleMenu.setUpdateUser(userId);
                    oaSysRoleMenuMapper.insert(roleMenu);
                }
            }
        }
    }

    /**
     * 更新角色与部门关联
     * @param roleReceive
     * @param userId
     * @param date
     */
    public void getRoleOffice (RoleReceive roleReceive,Long userId,Date date){
        List<Long> resList=new ArrayList<>();
        String tag=TokenUtil.getTag();
        //选择的角色
        List<Long> selectList=roleReceive.getSelectOfficeList();
        List<OaSysRoleOffice> roleOfficeList=getRoleOfficeByRole(String.valueOf(roleReceive.getRoleId()));
        if(selectList==null||selectList.isEmpty()){
            QueryWrapper<OaSysRoleOffice> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(OaSysRoleOffice.ROLE_ID,roleReceive.getRoleId());
            oaSysRoleOfficeMapper.delete(queryWrapper);
        }else{
            List<Long> delteOfficeList=new ArrayList<>();
            for(OaSysRoleOffice role:roleOfficeList){
                if(!selectList.contains(role.getRoleId())){
                    delteOfficeList.add(role.getOfficeId());
                }
                resList.add(role.getOfficeId());
            }
            if(!delteOfficeList.isEmpty()){
                QueryWrapper<OaSysRoleOffice> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq(OaSysRoleOffice.ROLE_ID,roleReceive.getRoleId());
                queryWrapper.in(OaSysRoleOffice.OFFICE_ID,delteOfficeList);
                oaSysRoleOfficeMapper.delete(queryWrapper);
            }
        }
        if(selectList!=null&&!selectList.isEmpty()) {
            selectList.removeAll(resList);
            if (!selectList.isEmpty()) {
                OaSysRoleOffice roleOffice = null;
                for (int i = 0; i < selectList.size(); i++) {
                    roleOffice = new OaSysRoleOffice();
                    roleOffice.setLinkedId(IDUtil.nextId());
                    roleOffice.setOfficeId(selectList.get(i));
                    roleOffice.setRoleId(roleReceive.getRoleId());
                    roleOffice.setCreateTime(date);
                    roleOffice.setCreateUser(userId);
                    roleOffice.setUpdateTime(date);
                    roleOffice.setUpdateUser(userId);
                    roleOffice.setTag(tag);
                    oaSysRoleOfficeMapper.insert(roleOffice);
                }
            }
        }
    }

    /**
     * 查询角色管理菜单
     * @param roleId
     * @return
     */
    private List<OaSysRoleMenu> getRoleMenuByRole(String roleId){
        QueryWrapper<OaSysRoleMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysRoleMenu.ROLE_ID,roleId);
        List<OaSysRoleMenu> roleMenuList = oaSysRoleMenuMapper.selectList(queryWrapper);
        return roleMenuList;
    }

    /**
     * 查询角色部门
     * @param roleId
     * @return
     */
    private List<OaSysRoleOffice> getRoleOfficeByRole(String roleId){
        QueryWrapper<OaSysRoleOffice> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysRoleOffice.ROLE_ID,roleId);
        List<OaSysRoleOffice> roleOfficeList = oaSysRoleOfficeMapper.selectList(queryWrapper);
        return roleOfficeList;
    }

    /**
     * 删除角色
     *
     * @return
     */
    @Override
    public Rv getDeleteRole(RoleReceive roleReceive) {
        List<String> roleList=TokenUtil.getRoleDataScope();
        if(!roleList.contains(GlobalConfig.DATA_SCOPE_ALL)){
            throw PangException.create(EErrorCode.authErr);
        }
        if(CheckUtil.objIsEmpty(roleReceive.getRoleId())){
            throw PangException.create(EErrorCode.missingArg);
        }
        QueryWrapper<OaSysRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysRole.ROLE_ID,roleReceive.getRoleId());
        oaSysRoleMapper.delete(queryWrapper);
        return Rv.wrap(EErrorCode.deleteSuccess);
    }

    /**
     * 获取分配页面数据
     *
     * @return
     */
    @Override
    public Rv getAssignRole(Long roleId) {
        Long userId=TokenUtil.getTokenUserId();
        OaSysUser user = oaSysUserMapper.selectById(userId);
        List<SysUserResults> userList=getDistributionUserRole(roleId,user);
        return Rv.wrap(EErrorCode.success,userList);
    }

    public List<SysUserResults> getDistributionUserRole(Long roleId,OaSysUser user){
        // 生成数据权限过滤条件（dsf为dataScopeFilter的简写，在xml中使用 ${sqlMap.dsf}调用权限SQL）
        GlobalConfig config = new GlobalConfig();
        config.getSqlMap().put("dsf", officeServiceImpl.dataScopeFilter(user, "o", "a"));
        config.setRoleId(roleId);
        config.setUserId(user.getSysUserId());
        return oaSysUserMapper.sysUserList(config);
    }

    /**
     * 从角色中移除用户
     *
     * @return
     */
    @Override
    public Rv getOutRole(RoleReceive roleReceive) {
        // 查询用户角色
        QueryWrapper<OaSysUserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysUserRole.USER_ID, roleReceive.getSysUserId());
        queryWrapper.eq(OaSysUserRole.ROLE_ID, roleReceive.getRoleId());
        List<OaSysUserRole> rolesList = oaSysUserRoleMapper.selectList(queryWrapper);
        if(!rolesList.isEmpty()){
            oaSysUserRoleMapper.delete(Wrappers.<OaSysUserRole>lambdaQuery().eq(OaSysUserRole::getUserId, roleReceive.getSysUserId()).eq(OaSysUserRole::getRoleId, roleReceive.getRoleId()));
        }
        return Rv.wrap(EErrorCode.success);
    }

    /**
     * 角色分配列表
     *
     * @return
     */
    @Override
    public Rv getUserRole(Long roleId) {
        Long userId=TokenUtil.getTokenUserId();
        if(CheckUtil.objIsEmpty(roleId)){
            throw PangException.create(EErrorCode.missingArg);
        }
        OaSysUser user = oaSysUserMapper.selectById(userId);
        Map<String, Object> map = new HashMap<>(16);
        List<SysUserResults> userList=getDistributionUserRole(roleId,user);
        map.put("userList",userList);
        List<OaSysOffice>  officeList=officeServiceImpl.getOfficeList(userId);
        List<Map<String, Object>> officeMapList = ListToTreeUtil.getOfficeList(officeList,new ArrayList<>(),"");
        JSONArray officeResultList = ListToTreeUtil.listToTree(JSONArray.parseArray(JSON.toJSONString(officeMapList)),"id","pId","children");
        map.put("officeList",officeResultList);
        return Rv.wrap(EErrorCode.success,map);
    }

    /**
     * 点击机构获取人员
     *
     * @return
     */
    @Override
    public Rv getRoleInUser(Long officeId) {
        Long userId=TokenUtil.getTokenUserId();
        OaSysUser user = oaSysUserMapper.selectById(userId);
        List<Map<String, Object>> mapList = Lists.newArrayList();
        // 生成数据权限过滤条件（dsf为dataScopeFilter的简写，在xml中使用 ${sqlMap.dsf}调用权限SQL）
        GlobalConfig config = new GlobalConfig();
        config.getSqlMap().put("dsf", officeServiceImpl.dataScopeFilter(user, "o", "a"));
        config.setOfficeId(officeId);
        List userList = oaSysUserMapper.sysUserList(config);
        return Rv.wrap(EErrorCode.success,userList);
    }


    /**
     * 角色分配
     *
     * @return
     */
    @Override
    public Rv getRoleAllocation(Long roleId,List<Long> userIdList) {
        if(userIdList.isEmpty()||CheckUtil.objIsEmpty(roleId)){
            throw PangException.create(EErrorCode.missingArg);
        }
        List<Long> resList=new ArrayList<>();
        // 查询全部的
        QueryWrapper<OaSysUserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysUserRole.ROLE_ID, String.valueOf(roleId));
        List<OaSysUserRole> roleList=oaSysUserRoleMapper.selectList(queryWrapper);
        if(userIdList.isEmpty()){
            QueryWrapper<OaSysUserRole> delteQueryWrapper = new QueryWrapper<>();
            delteQueryWrapper.eq(OaSysUserRole.ROLE_ID, String.valueOf(roleId));
            oaSysUserRoleMapper.delete(delteQueryWrapper);
        }else{
            List<Long> deleteUserId=new ArrayList<>();
            for(OaSysUserRole role:roleList){
                if(!userIdList.contains(role.getRoleId())){
                    deleteUserId.add(role.getUserId());
                }
                resList.add(role.getRoleId());
            }
            if(!deleteUserId.isEmpty()){
                QueryWrapper<OaSysUserRole> delteQueryWrapper = new QueryWrapper<>();
                delteQueryWrapper.eq(OaSysUserRole.ROLE_ID, String.valueOf(roleId));
                delteQueryWrapper.in(OaSysUserRole.USER_ID, deleteUserId);
                oaSysUserRoleMapper.delete(delteQueryWrapper);
            }
        }
        if(!userIdList.isEmpty()) {
            userIdList.removeAll(resList);
            if (userIdList.size() > 0) {
                OaSysUserRole userRole = null;
                for (int i = 0; i < userIdList.size(); i++) {
                    userRole = new OaSysUserRole();
                    userRole.setRoleId(roleId);
                    userRole.setUserId(userIdList.get(i));
                    oaSysUserRoleMapper.insert(userRole);
                }
            }
        }
        return Rv.wrap(EErrorCode.success);
    }

}
